package com.dxy.hms.mybatis;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import com.dxy.hms.auth.LoginUser;
import com.dxy.hms.utils.LoginUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.reflection.MetaObject;

import java.time.LocalDateTime;

@Slf4j
public class MybatisPlusMetaObjectHandler implements MetaObjectHandler {

    private static final String FIELD_CREATE_USER_ID = "createUserId";
    private static final String FIELD_CREATE_USER_NAME = "createUserName";
    private static final String FIELD_CREATE_TIME = "createTime";
    private static final String FIELD_UPDATE_USER_ID = "updateUserId";
    private static final String FIELD_UPDATE_USER_NAME = "updateUserName";
    private static final String FIELD_UPDATE_TIME = "updateTime";

    /**
     * strictInsertFill 精确填充insert字段
     * strictUpdateFill 精确填充update字段
     * 1. 参数解析：
     * （1）第一个参数是entity对象
     * （2）第二个是要填充的字段名（注意不是数据库列名）
     * （3）第三个是字段类型
     * （4）第四个是填充的字段值
     * 2. 填充规则：
     * （1）MetaObjectHandler实现类必须交给Spring管理（@Component或者@Bean）
     * （2）entity类是要填充的字段必须用@TableField注解且写名fill属性（@TableField(fill = FieldFill.INSERT)）
     * （3）entity中已经有值了不填充，填充的值是null值也不填充
     * （4）当表中没有这个列（entity中也没有这个字段）时，会自动忽略不报错
     * 3. 开发规范---每个表都应该有的审计字段，且类型保持统一：
     * （1）is_deleted tinyint unsigned 逻辑删除，0-正常，1-已删除
     * （2）create_user_id bigint unsigned 创建人id
     * （3）create_user_name varchar(30) 创建人用户名，冗余保存
     * （4）create_time datetime 创建时间
     * （5）update_user_id bigint unsigned 最后更新人id
     * （6）update_user_name varchar(30) 最后更新人名称，冗余保存
     * （7）update_time datetime 最后更新时间
     */

    @Override
    public void insertFill(MetaObject metaObject) {
        this.strictInsertFill(metaObject, FIELD_CREATE_USER_ID, Long.class, getCurrentUserId());
        this.strictInsertFill(metaObject, FIELD_CREATE_USER_NAME, String.class, getCurrentUserName());
        this.strictInsertFill(metaObject, FIELD_CREATE_TIME, LocalDateTime.class, LocalDateTime.now());
        this.strictInsertFill(metaObject, FIELD_UPDATE_USER_ID, Long.class, getCurrentUserId());
        this.strictInsertFill(metaObject, FIELD_UPDATE_USER_NAME, String.class, getCurrentUserName());
        this.strictInsertFill(metaObject, FIELD_UPDATE_TIME, LocalDateTime.class, LocalDateTime.now());
    }


    @Override
    public void updateFill(MetaObject metaObject) {
        this.strictUpdateFill(metaObject, FIELD_UPDATE_USER_ID, Long.class, getCurrentUserId());
        this.strictUpdateFill(metaObject, FIELD_UPDATE_USER_NAME, String.class, getCurrentUserName());
        this.strictUpdateFill(metaObject, FIELD_UPDATE_TIME, LocalDateTime.class, LocalDateTime.now());
    }

    private Long getCurrentUserId() {
        LoginUser loginUser = LoginUtil.getLoginUser();
        return loginUser != null ? loginUser.getUserId() : null;
    }

    private String getCurrentUserName() {
        LoginUser loginUser = LoginUtil.getLoginUser();
        return loginUser == null ? StrUtil.subPre(Thread.currentThread().getName(), 30) :
                StrUtil.subPre(loginUser.getUserName(), 30);
    }
}
